/*
 * omap3_dss.c
 *
 *  Created on: Jan 7, 2011
 *      Author: qian
 */

#include <common.h>
#include <asm/io.h>
#include <dss.h>


static const struct panel_config panel_cfg = {
	.timing_h	= 0x00f00b03, /* Horizantal timing */
	.timing_v	= 0x00300301, /* Vertical timing */
	.pol_freq	= 0x00033000, /* Pol Freq */
	.divisor	= 0x00090001, /* 72Mhz Pixel Clock */
	.lcd_size	= 0x01df013f, /* 1024x768 */
	.panel_type	= 0x04, /* STNTFT */
	.data_lines	= 0x03, /* 24 Bit RGB */
	.load_mode	= 0x02, /* Frame Mode */
	.panel_color	= 0x00FF8000 /* ORANGE */
};
/*
 * Display controller register I/O routines
 */
static __inline__ u32 dispc_reg_in(u32 offset)
{
	return readl(DSS_REG_BASE + DISPC_REG_OFFSET + offset);
}

static __inline__ u32 dispc_reg_out(u32 offset, u32 val)
{
	writel(val, DSS_REG_BASE + DISPC_REG_OFFSET + offset);
	return val;
}
static __inline__ u32 dispc_reg_merge(u32 offset, u32 val, u32 mask)
{
	u32 addr = DSS_REG_BASE + DISPC_REG_OFFSET + offset;
	u32 new_val = (readl(addr) & ~mask) | (val & mask);

	writel(new_val, addr);
	return new_val;
}

 /*
  * Configure Panel Specific Parameters
  */
 void omap3_dss_init()
 {
		/* display controller programming */
		u32 val;
		u32 control;
		u32 config;

		val = dispc_reg_in(DISPC_CONFIG);
		val &= ~DISPC_CONFIG_LOADMODE_MASK;
		val |= DISPC_CONFIG_LOADMODE_FRDATLFFR;
		val |= DISPC_CONFIG_LCDALPHAENABLE;
		dispc_reg_out(DISPC_CONFIG, val);

		/* configure LCD timing */
		//omap2_disp_config_lcd(1, 15, 11, 3, 3, 3, 1, 32);
		//DISPC_TIMING_H    = 0x00f00b03
		dispc_reg_out(DISPC_TIMING_H, 0x00f00b03);
		//DISPC_TIMING_V    = 0x00300301
		dispc_reg_out(DISPC_TIMING_V, 0x00300301);
		//DISPC_DIVISOR     = 0x00090001
		dispc_reg_out(DISPC_DIVISOR, 0x00090001);
		control = dispc_reg_in(DISPC_CONTROL);
		control |= DISPC_CONTROL_GPOUT1 |
			   DISPC_CONTROL_GPOUT0 |
			   DISPC_CONTROL_TFTDATALINES_OALSB24B |
			   DISPC_CONTROL_STNTFT;
		dispc_reg_out(DISPC_CONTROL, control);

		/* configure polarity */
		val = DISPC_POL_FREQ_IHS | DISPC_POL_FREQ_IVS |
		      DISPC_POL_FREQ_RF  | DISPC_POL_FREQ_ONOFF;
		dispc_reg_out(DISPC_POL_FREQ, val);

		/* set the panel size */
		//omap2_disp_set_panel_size(OMAP2_OUTPUT_LCD, 320, 480);
		//DISPC_SIZE_LCD    = 0x01df013f
		dispc_reg_out(DISPC_SIZE_LCD, 0x01df013f);

		/* setup the graphics layer */
		//omap2_disp_config_gfxlayer(320, 480, 32);
		config = dispc_reg_in(DISPC_CONFIG);

			config |= (DISPC_CONFIG_LOADMODE_PGTABUSETB |
				   DISPC_CONFIG_LOADMODE_FRDATLEFR);

			/* This driver doesn't currently support the video windows, so
			 * we force the palette/gamma table to be a palette table and
			 * force both video windows to be disabled.
			 */
			config &= ~DISPC_CONFIG_PALETTEGAMMATABLE;

			//DISPC_GFX_FIFO_TH = 0x0bb809c4
			dispc_reg_out(DISPC_GFX_FIFO_THRESHOLD, 0x0bb809c4);


			//DISPC_GFX_POSITION= 0x00000000
			dispc_reg_out(DISPC_GFX_POSITION, 0x00000000);
			//DISPC_GFX_WIN_SKP = 0x00000000
			dispc_reg_out(DISPC_GFX_WINDOW_SKIP, 0x00000000);

			dispc_reg_out(DISPC_CONFIG, config);
			//DISPC_GFX_ATTRIB  = 0x00000099
			dispc_reg_out(DISPC_GFX_ATTRIBUTES, 0x00000099);
			//DISPC_GFX_SIZE    = 0x01df013f
			dispc_reg_out(DISPC_GFX_SIZE, 0x01df013f);
		dispc_reg_out(DISPC_GFX_ROW_INC,   1);
		dispc_reg_out(DISPC_GFX_PIXEL_INC, 1);

		//DISPC_GLOBAL_ALPHA= 0x00ff00ff
		dispc_reg_out(DISPC_GLOBAL_ALPHA, 0x00ff00ff);

		/* Setup dispc_control */
		val =	DISPC_CONTROL_GPOUT0 |
			DISPC_CONTROL_GPOUT1 |
			DISPC_CONTROL_TFTDATALINES_OALSB24B |
			DISPC_CONTROL_STNTFT |
			DISPC_CONTROL_PCKFREEENABLE |
			DISPC_CONTROL_LCDENABLEPOL_ACTIVEHIGH;
		dispc_reg_out(DISPC_CONTROL, val);

 	struct dispc_regs *dispc = (struct dispc_regs *) OMAP3_DISPC_BASE;

 	writel(panel_cfg.timing_h, &dispc->timing_h);
 	writel(panel_cfg.timing_v, &dispc->timing_v);
 	writel(panel_cfg.pol_freq, &dispc->pol_freq);
 	writel(panel_cfg.divisor, &dispc->divisor);
 	writel(panel_cfg.lcd_size, &dispc->size_lcd);
 	writel((panel_cfg.load_mode << FRAME_MODE_SHIFT), &dispc->config);
 	writel(((panel_cfg.panel_type << TFTSTN_SHIFT) |
 		(panel_cfg.data_lines << DATALINES_SHIFT)), &dispc->control);
 	writel(panel_cfg.panel_color, &dispc->default_color0);
 }

 /*
  * Enable LCD and DIGITAL OUT in DSS
  */
 void omap3_dss_enable(void)
 {
 	struct dispc_regs *dispc = (struct dispc_regs *) OMAP3_DISPC_BASE;
 	u32 l = 0;

 	l = readl(&dispc->control);
 	l |= DISPC_ENABLE;
 	writel(l, &dispc->control);

	/* LCD */
	dispc_reg_merge(DISPC_CONTROL, DISPC_CONTROL_GOLCD,
			DISPC_CONTROL_GOLCD);
 }
